#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include <Metro.h>

// These are the interrupt and control pins
#define ADAFRUIT_CC3000_IRQ   3  // MUST be an interrupt pin!
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10
// Use hardware SPI for the remaining pins
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
                                         SPI_CLOCK_DIVIDER); // you can change this clock speed

#define WLAN_SSID       "Matrix"           // cannot be longer than 32 characters!
#define WLAN_PASS       "ursacheundwirkung123"
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY   WLAN_SEC_WPA2

// What page to grab!
//#define WEBSITE "api.thingspeak.com"

// Carriots parameters
#define WEBSITE  "api.carriots.com"
#define API_KEY "fbdd9def209ba543f00552d2c1cbb08682c11ac6618a95bb6b9d1b6fbf8999f2"
#define DEVICE  "Garduino@m3rlin.m3rlin"

uint32_t ip;

Metro heartBeat = Metro(1000);

void SetupWifi()
{
  /* Initialise the module */
  Serial.println(F("begin... "));
  if (!cc3000.begin()) {
    Serial.println(F("Couldn't begin()! Check your wiring?"));
    return;
  }
  Serial.println();
  
  //Connect
  Serial.println(F("connect to Accesspoint... "));
  if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
    Serial.println(F("Failed!"));
    return;
  }
  Serial.println();
  
  /* Wait for DHCP to complete */
  Serial.println(F("\nRequest DHCP"));
  unsigned long startT = millis();
  while ((!cc3000.checkDHCP()) && (!isTimeout(startT,10000)))
  {delay(200);}  
 
  // Get the website IP & print it
  ip = 0;
  Serial.print(WEBSITE); Serial.print(F(" -> "));
  while ((ip == 0) && (!isTimeout(startT,10000))) {
    if (! cc3000.getHostByName(WEBSITE, &ip)) {
      Serial.println(F("Couldn't resolve!"));
    }
    delay(500);
  }
  cc3000.printIPdots(ip);
  Serial.println();
}

boolean isTimeout(unsigned long startTime, int timeOut)
{
  if((millis()-startTime)>timeOut){
    Serial.println(F(" TimeOut! "));
    return true;
  }
  else
  {
    return false;
  }
}

// Convert double to string
String doubleToString(float input,int decimalPlaces){
  if(decimalPlaces!=0){
    String string = String((int)(input*pow(10,decimalPlaces)));
      if(abs(input)<1){
        if(input>0)
          string = "0"+string;
        else if(input<0)
          string = string.substring(0,1)+"0"+string.substring(1);
      }
      return string.substring(0,string.length()-decimalPlaces)+"."+string.substring(string.length()-decimalPlaces);
    }
  else {
    return String((int)input);
  }
}

void LogValues(float Temp, int Moisture)
{
   
  // Prepare JSON for Carriots & get length
  int length = 0;
  String TempStr = doubleToString(Temp,2);
  String data = "{\"protocol\":\"v2\",\"device\":\""+String(DEVICE)+"\",\"at\":\"now\",\"data\":{\"Temperature\":"+String(TempStr)+",\"Moisture\":"+String(Moisture)+"}}";
  length = data.length();
  
  // Print Info for debug purposes
  Serial.println();
  Serial.println(F("start loggint to carriots.com:"));
  Serial.println("carriots.apikey: " + String(API_KEY));
  Serial.println("Content-Length: " + String(length));
  Serial.println(data);
  
  // Send request
  Adafruit_CC3000_Client client = cc3000.connectTCP(ip, 80);
  if (client.connected()) {
    Serial.println("Connected!");
    client.println("POST /streams HTTP/1.1");
    client.println("Host: api.carriots.com");
    client.println("Accept: application/json");
    client.println("User-Agent: Arduino-Carriots");
    client.println("Content-Type: application/json");
    client.println("carriots.apikey: " + String(API_KEY));
    client.println("Content-Length: " + String(length));
    client.println("Connection: close");
    client.println();
    client.println(data);
    
  } else {
    return;
  }
  
  Serial.println(F("-------------------------------------"));
  unsigned long startT = millis();
  while (client.connected() && (!isTimeout(startT,10000))) {
    while (client.available() && (!isTimeout(startT,10000))) {
      char c = client.read();
      Serial.print(c); 
    }
  }
  client.close();
  Serial.println(F("\n-------------------------------------"));
}


void setup(){
  Serial.begin(115200);
  
  Serial.println(F("Sreial2Cariots"));
  SetupWifi();
  heartBeat.reset();
}

void loop(){
  if (heartBeat.check()) {
    Serial.println('#');Serial.flush();
  }
  
  commands();
  
  delay(1);
}

char buff[3];
byte buffIdx;
const byte STATE_WAIT_CMD = 1;
const byte STATE_READ_TEMP = 2;
const byte STATE_READ_MOIST = 3;
byte state;
float rTemp;
int rMoist;

void commands(){
  if (Serial.available() > 0){
    char inByte = Serial.read();

    if (inByte=='t'){
      state = STATE_READ_TEMP;
      buffIdx = 0;
    }
    else if (inByte=='m'){
      state = STATE_READ_MOIST;
      buffIdx = 0;
    }
    else if (inByte==';'){
      LogValues(rTemp,rMoist);
    }
    else if (isDigit(inByte) && ((state == STATE_READ_TEMP) || (state == STATE_READ_MOIST))){
      buff[buffIdx]=inByte;
      buffIdx++;
      if (buffIdx==3) {
        String tmp = buff;
        if (state == STATE_READ_TEMP) 
          rTemp = tmp.toInt()/10.0;
        if (state == STATE_READ_MOIST) 
          rMoist = tmp.toInt();
        Serial.print("Sate: ");
        Serial.print(state);Serial.print("\t");
        Serial.print("Temp: ");
        Serial.print(rTemp);Serial.print("\t");
        Serial.print("Moisture: ");
        Serial.println(rMoist);
        state = STATE_WAIT_CMD;
        buffIdx = 0;
      }
    }
  }  
}

